package gui;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;

import javax.swing.JLabel;
import javax.swing.BoxLayout;
import javax.swing.JButton;

import constant.Constant;
import net.sourceforge.jdatepicker.impl.JDatePanelImpl;
import net.sourceforge.jdatepicker.impl.JDatePickerImpl;
import net.sourceforge.jdatepicker.impl.UtilCalendarModel;
import business.BusinessImpl;
import dto.DTOAbsence;
import dto.DTOClass;
import dto.DTOContact;

import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JMenuItem;

import java.awt.GridLayout;

import javax.swing.JTable;

public class Main extends JFrame {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private JPanel contentPane;
	private TablePeriod table;
	// date used to select absence
	private Calendar selectedDate;
	// dates used to defined to length of the summary
	private Calendar resumeDateStart;
	private Calendar resumeDateEnd;
	// the selected class on the JList
	private DTOClass selectedClass;
	private JLabel lblClass;
	private ListClass listclass;
	private BusinessImpl businessImpl = new BusinessImpl();
	private final JDatePickerImpl datePicker;
	private final JDatePickerImpl datePickerFirst;
	private final JDatePickerImpl datePickerSecond;
	private JTable tblSummary;
	private JLabel lblDate;

	/**
	 * Create the frame.
	 */
	public Main(final DTOContact contact) {

		this.setTitle("Gestion des absences");
		
		// define the interface
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 772, 482);

		// define the menu
		JMenuBar menuBar = new JMenuBar();
		setJMenuBar(menuBar);

		JMenu mnOptions = new JMenu("Options");
		menuBar.add(mnOptions);

		JMenu mnClasse = new JMenu("Classe");
		mnOptions.add(mnClasse);

		JMenuItem mntmAjouter = new JMenuItem("Ajouter une classe");
		mntmAjouter.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// launch
				ClassManaging classManaging = new ClassManaging();
				classManaging.setVisible(true);
				

				listclass.setData(getFormatedClassList(contact));
				//.repaint();

			}
		});
		mnClasse.add(mntmAjouter);

		JMenuItem mntmModifierLaClasse = new JMenuItem(
				"Modifier la classe selectionnée");
		mntmModifierLaClasse.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// launch classManaging and select the current class
				ClassManaging classManaging = new ClassManaging();
				classManaging.setSelectedClass(selectedClass);
				classManaging.setVisible(true);
				
				listclass.setData(getFormatedClassList(contact));
				listclass.repaint();

			}
		});
		mnClasse.add(mntmModifierLaClasse);

		JMenuItem mntmGrerUnContact = new JMenuItem("Gérer un contact");
		mntmGrerUnContact.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// launch the contact managing
				ContactManaging test = new ContactManaging();
				test.setSelectedContact(null);
				test.setVisible(true);
				
				listclass.setData(getFormatedClassList(contact));
				listclass.repaint();
				
				RefreshpnlAbsence();

			}
		});
		mnOptions.add(mntmGrerUnContact);

		// define the content of the frame
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(new BorderLayout(0, 0));

		selectedDate = Calendar.getInstance();

		// add a list on the right
		listclass = new ListClass(getFormatedClassList(contact));
		listclass.addListSelectionListener(new ListSelectionListener() {

			@Override
			public void valueChanged(ListSelectionEvent e) {
				// when something is selected on the list refresh both panel
				RefreshpnlAbsence();
				RefreshpnlSummary();
			}
		});
		contentPane.add(listclass, BorderLayout.WEST);

		// create 2 tab for the summary and the absence managing
		JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);

		contentPane.add(tabbedPane, BorderLayout.CENTER);

		// create the tab managing the absence
		JPanel pnlClass = new JPanel();
		tabbedPane.addTab("Saisie des absences", null, pnlClass, null);
		pnlClass.setLayout(new BorderLayout(0, 0));

		JPanel pnlDateSelection = new JPanel();
		pnlClass.add(pnlDateSelection, BorderLayout.SOUTH);
		pnlDateSelection.setLayout(new BoxLayout(pnlDateSelection,
				BoxLayout.X_AXIS));

		JButton btnback = new JButton("<");
		btnback.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// refresh the panel managing absence
				selectedDate.add(Calendar.DATE, -1);
				RefreshpnlAbsence();
			}
		});
		pnlDateSelection.add(btnback);

		// Panel managing the date
		UtilCalendarModel model = new UtilCalendarModel();
		JDatePanelImpl datePanel = new JDatePanelImpl(model);
		model.setValue(selectedDate);
		model.setSelected(true);
		datePicker = new JDatePickerImpl(datePanel);
		datePicker.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				selectedDate = (Calendar) datePicker.getModel().getValue();

				RefreshpnlAbsence();
			}
		});
		pnlDateSelection.add(datePicker);

		JButton btnnext = new JButton(">");
		btnnext.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				selectedDate.add(Calendar.DATE, 1);
				RefreshpnlAbsence();
			}
		});
		pnlDateSelection.add(btnnext);

		// Load the first class of the contact at first load
		ArrayList<DTOClass> clasS = businessImpl.getClassByContact(contact);
		clasS = businessImpl.sortClass(clasS);
		if (clasS.size() > 0) {
			selectedClass = clasS.get(0);
			// create a new tablePeriod used to manage absence
			table = new TablePeriod(selectedClass, selectedDate);
		}

		lblClass = new JLabel(clasS.get(0).getName().toUpperCase() + " / "
				+ Constant.gettextdate(selectedDate));
		pnlClass.add(lblClass, BorderLayout.NORTH);

		pnlClass.add(new JScrollPane(table), BorderLayout.CENTER);

		JPanel pnlSummary = new JPanel();

		// Define the panel managing the summary
		tabbedPane.addTab("R\u00E9sum\u00E9 des absences", null, pnlSummary,
				null);

		pnlSummary.setLayout(new BorderLayout(0, 0));

		resumeDateStart = Calendar.getInstance();
		resumeDateStart.set(2014, 0, 1);
		resumeDateEnd = Calendar.getInstance();

		UtilCalendarModel modelFirst = new UtilCalendarModel();
		JDatePanelImpl datePanelFirst = new JDatePanelImpl(modelFirst);
		modelFirst.setValue(resumeDateStart);
		modelFirst.setSelected(true);
		datePickerFirst = new JDatePickerImpl(datePanelFirst);
		datePickerFirst.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				resumeDateStart = (Calendar) datePickerFirst.getModel()
						.getValue();
				// refresh the summary panel
				RefreshpnlSummary();
			}
		});

		UtilCalendarModel modelSecond = new UtilCalendarModel();
		JDatePanelImpl datePanelSecond = new JDatePanelImpl(modelSecond);
		modelSecond.setValue(resumeDateEnd);
		modelSecond.setSelected(true);
		datePickerSecond = new JDatePickerImpl(datePanelSecond);
		datePickerSecond.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				resumeDateEnd = (Calendar) datePickerSecond.getModel()
						.getValue();

				RefreshpnlSummary();
			}
		});

		JPanel pnlMultiDateSelection = new JPanel();
		pnlSummary.add(pnlMultiDateSelection, BorderLayout.SOUTH);
		pnlMultiDateSelection.setLayout(new GridLayout(1, 0, 0, 0));
		pnlMultiDateSelection.add(datePickerFirst);
		pnlMultiDateSelection.add(datePickerSecond);

		lblDate = new JLabel(selectedClass.getName().toUpperCase() + " / "
				+ "Du : " + Constant.gettextdate(resumeDateStart) + " au : "
				+ Constant.gettextdate(resumeDateEnd));
		pnlSummary.add(lblDate, BorderLayout.NORTH);

		tblSummary = new JTable();
		pnlSummary.add(new JScrollPane(tblSummary), BorderLayout.CENTER);
		RefreshpnlSummary();
		tabbedPane.addChangeListener(new ChangeListener() {

			@Override
			public void stateChanged(ChangeEvent e) {
				// add a change listener to the tabbedpane to refresh both panel
				RefreshpnlAbsence();
				RefreshpnlSummary();

			}
		});
	}

	private void RefreshpnlSummary() {
		// refresh the summary
		lblDate.setText(selectedClass.getName().toUpperCase() + " / " + "Du : "
				+ Constant.gettextdate(resumeDateStart) + " au :"
				+ Constant.gettextdate(resumeDateEnd));

		Object[][] data;

		ArrayList<ArrayList<Object>> dataSummary = new ArrayList<ArrayList<Object>>();
		ArrayList<Object> temp = new ArrayList<Object>();
		int numberOfAbsence = 0;
		int numberOfAbsenceExcused = 0;
		int numberOfPeriod = 0;

		// Create the arraylist contaaining th data nddded for the summary
		for (DTOContact dtoContact : businessImpl
				.getContactsByClass(selectedClass)) {
			if (dtoContact.getTypeOfContact() == Constant
					.typeofcontact("STUDENT")) {
				numberOfAbsence = 0;
				numberOfPeriod = 0;
				temp = new ArrayList<Object>();
				for (DTOAbsence dtoAbsence : businessImpl
						.getAbsenceByContact(dtoContact)) {

					if (dtoAbsence.getDate().getTime() > resumeDateStart
							.getTimeInMillis()
							&& dtoAbsence.getDate().getTime() < resumeDateEnd
									.getTimeInMillis()) {
						numberOfAbsence++;

						if (dtoAbsence.getTypeOfAbsence() == 1)
							numberOfAbsenceExcused++;

						for (char ch : dtoAbsence.getPeriod().toCharArray()) {
							if (ch == '1') {
								numberOfPeriod++;
							}
						}
					}
				}
				temp.add(dtoContact);
				temp.add(numberOfAbsence);
				temp.add(numberOfAbsenceExcused);
				temp.add(numberOfPeriod);
				temp.add(numberOfPeriod / 5);
				dataSummary.add(temp);
			}
		}
		if (dataSummary.size() > 0) {
			data = new Object[dataSummary.size()][dataSummary.get(0).size()];
		// add the data to the table
		data = new Object[dataSummary.size()][dataSummary.get(0).size()];

			for (int i = 0; i < data.length; i++) {
				for (int j = 0; j < data[i].length; j++) {
					data[i][j] = dataSummary.get(i).get(j);
				}
			}

			tblSummary.setModel(new DefaultTableModel(data,
					Constant.SUMMARY_COLUMNNAMES));
		} else
			tblSummary.setModel(new DefaultTableModel());

	}

	private void RefreshpnlAbsence() {
		// refresh the panl managing absences

		String selectedclassname = null;

		// check if a class is selected
		if (listclass.getSelectedIndex() != -1)
			selectedclassname = listclass.getData()[listclass
					.getSelectedIndex()];

		// /if a class is selected updat selectedClass
		if (selectedclassname != null) {
			if (selectedclassname.startsWith("-> "))
				selectedClass = businessImpl.getClassByName(selectedclassname
						.substring(3));

		}

		// update the table and the datepicker
		if (selectedClass != null) {
			table.refreshData(selectedClass, selectedDate);
			lblClass.setText((selectedClass.getName().toUpperCase() + " / " + Constant
					.gettextdate(selectedDate)));

			table.repaint();
			UtilCalendarModel model = (UtilCalendarModel) datePicker.getModel();
			model.setValue(selectedDate);
			model.setSelected(true);
		}
	}

	private String[] getFormatedClassList(DTOContact contact) {
		// methode to get the list of th JList containing all classes related to
		// a contact

		ArrayList<DTOClass> clasS = businessImpl.getClassByContact(contact);

		ArrayList<String> finalList = new ArrayList<String>();
		finalList.add(contact.getFirstname() + " " + contact.getLastname());
		ArrayList<String> student = new ArrayList<String>();
		ArrayList<String> teacher = new ArrayList<String>();
		ArrayList<String> holder = new ArrayList<String>();
		// check if the contact is a student
		if (contact.getTypeOfContact() == Constant.typeofcontact("STUDENT")) {
			for (DTOClass dtoClass : clasS) {
				student.add("-> " + dtoClass);
			}
		}
		// check if the contact is a teacher if ys it update the teacher and
		// holder list
		else if (contact.getTypeOfContact() == Constant
				.typeofcontact("TEACHER")) {
			for (DTOClass dtoClass : clasS) {
				teacher.add("-> " + dtoClass);

			}
			for (DTOClass dtoClass : businessImpl.getAllClass()) {
				if (dtoClass.getHolder_id() == contact.getId()) {
					holder.add("-> " + dtoClass);
				}
			}
			if (teacher != null)
				Collections.sort(teacher, new Comparator<Object>() {
					@Override
					public int compare(Object e1, Object e2) {
						String id1 = ((String) e1);
						String id2 = ((String) e2);

						// ascending order
						return id1.compareTo(id2);

						// descending order
						// return id2.compareTo(id1);
					}
				});
			if (holder != null)
				Collections.sort(holder, new Comparator<Object>() {
					@Override
					public int compare(Object e1, Object e2) {
						String id1 = ((String) e1);
						String id2 = ((String) e2);

						// ascending order
						return id1.compareTo(id2);

						// descending order
						// return id2.compareTo(id1);
					}
				});

		}

		// create the final list
		student.add(0, "Elève de :");
		teacher.add(0, "Professeur de :");
		holder.add(0, "Titulaire de :");
		if (holder.size() > 1)
			finalList.addAll(holder);
		if (teacher.size() > 1)
			finalList.addAll(teacher);
		if (student.size() > 1)
			finalList.addAll(student);

		String[] ret = new String[finalList.size() + 1];
		for (int i = 0; i < finalList.size(); i++) {
			ret[i] = finalList.get(i);
		}

		

		return ret;
	}

}
